#ifndef __COMMON_H_
#define __COMMON_H_

#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifdef DEBUG
#define mark_line() \
    do {\
    fprintf(stderr, "\n%s:%d:\n", __FILE__, __LINE__);\
    } while (0)
#else
#define mark_line()
#endif

#define ADD_PTR(ptr, off) ((void*)(((char*)ptr) + (off)))

#define SUB_PTR(ptr, off) ((void*)(((char*)ptr) - (off)))

#define COUNTOF(A) (sizeof(A)/sizeof((A)[0]))

bool str_end_of(const char* s, const char* key);

bool str_iend_of(const char* s, const char* key);

int str_ncat(char* s, int size, const char* cat);

char* make_string(const char* format, ...);

bool file_exists(const char* path);

bool is_directory(const char* path);

/*---------------- simple c vector ----------------*/
int sv_init(void** v);
int sv_push_ptr(void** v, const void* ptr);
int sv_push_size(void** v, void* ptr, size_t size);
int sv_count(void* v);
void sv_free(void* v);

int svs_init(void* pv);
int svs_push_ptr(void* pv, const void* ptr);
int svs_push_size(void* pv, void* ptr, size_t size);

#define DECLARE_SV(type) \
typedef type* sv_##type;\
int sv_init_##type(sv_##type* v);\
int sv_push_##type(sv_##type* v, type ptr);\
int sv_pushp_##type(sv_##type* v, type* ptr);\
int sv_count_##type(sv_##type v);\
void sv_free_##type(sv_##type v);

#define DEFINE_SV(type) \
typedef type* sv_##type;\
int sv_init_##type(sv_##type* v)\
{\
    return sv_init((void**)v);\
}\
int sv_push_##type(sv_##type* v, type ptr)\
{\
    return sv_push_size((void**)v, (void*)&ptr, sizeof(type));\
}\
int sv_pushp_##type(sv_##type* v, type* ptr)\
{\
    return sv_push_size((void**)v, (void*)ptr, sizeof(type));\
}\
int sv_count_##type(sv_##type v)\
{\
    return sv_count((void*)v);\
}\
void sv_free_##type(sv_##type v)\
{\
    sv_free((void*)v);\
}
/*---------------- simple c vector ----------------*/

typedef void* ptr_t;

DECLARE_SV(ptr_t)

/*---------------- simple memory pool ----------------*/
typedef struct auto_cmem_t
{
    sv_ptr_t ptr;
} auto_cmem_t;

void cmem_init(auto_cmem_t* mp);

int cmem_push(auto_cmem_t* mp, void* p);

void* cmem_malloc(auto_cmem_t* mp, size_t size);

void* cmem_calloc(auto_cmem_t* mp, size_t size, size_t count);

// may be very slow
void* cmem_realloc(auto_cmem_t* mp, void* ptr, size_t size);

char* cmem_strdup(auto_cmem_t* mp, const char* ptr);

void cmem_free(auto_cmem_t* mp);
/*---------------- simple memory pool ----------------*/

/*
#ifdef PRINT_PROCESS
#define dbg(x) x
#else
#define dbg(...)
#endif
*/

#ifdef __cplusplus
}
#endif

#endif  // __COMMON_H_